package com.gxa.security.filter;

import com.alibaba.fastjson.JSONObject;
import com.gxa.security.entity.SecurityUser;
import com.gxa.security.security.TokenHandler;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录认证
 */
public class TokenAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;
    private TokenHandler tokenHandler;
    private RedisTemplate redisTemplate;

    public TokenAuthenticationFilter(AuthenticationManager authenticationManager, TokenHandler tokenHandler, RedisTemplate redisTemplate) {
        this.authenticationManager = authenticationManager;
        this.tokenHandler = tokenHandler;
        this.redisTemplate = redisTemplate;
        this.setPostOnly(false);
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/app/sys/login","POST"));
    }

    //获取客户端提交用户名和密码
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        //获取表单提交数据
           String username = request.getParameter("username");
           String password = request.getParameter("password");
            System.out.println(username);
            System.out.println(password);
           return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username,password, new ArrayList<>()));
    }
    //认证成功调用的方法
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        //认证成功，得到认证成功之后用户信息
        SecurityUser user = (SecurityUser)authResult.getPrincipal();
        //根据用户名生成token
        String token = tokenHandler.createToken(user.getCurrentUserInfo().getName());
        //把用户名称和用户权限列表放到redis
        redisTemplate.opsForValue().set(user.getCurrentUserInfo().getName(),token);
        redisTemplate.opsForValue().set(user.getCurrentUserInfo().getName()+"1",user.getPermissionValueList());
        response.setContentType("application/json;charset=utf-8");
        Map result = new HashMap<>();
        result.put("code",200);
        result.put("msg","登录成功");
        response.getWriter().write(JSONObject.toJSONString(result));
        response.setHeader("Access-Control-Expose-Headers","Authorization");
        //响应头返回token
        response.setHeader("Authorization",token);
        response.getWriter().flush();
        response.getWriter().close();
    }
    //认证失败调用的方法
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        Map result = new HashMap<>();
        result.put("code",500);
        result.put("msg","认证错误");
        response.getWriter().write(JSONObject.toJSONString(result));
        response.getWriter().flush();
        response.getWriter().close();
    }
}
